/*
   FieldVis - A Tool for Visualizing Astrophysical Magnetohydrodynamic Flow
   
   Copyright (C) 2006 - 2008     FieldVis Development Team
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
  
   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

   File        : camera.cpp
   Author      : Matt Heinzen  (heinzen@cs.umn.edu)
                 Digital Technology Center - University of Minnesota
*/

#ifndef _CAMERA_H_
#define _CAMERA_H_


/*#define CAMERA_TURN_ANGLE (M_PI / 32.0)*/
#define CAMERA_KEY_DIST 0.1
#define CAMERA_MOUSE_DIST (CAMERA_KEY_DIST * 0.1)

#include "Vector3D.h"
#include "Matrix4x4.h"
#include "flowviewer.h"


class Camera
{
public:
   // default constructor/destructor
   Camera()    { }
   ~Camera()   { }

   // camera position and orientation vectors
   Vector3D Pos, Look, Up, Side;

   // copies camera position and orientation to supplied vectors
   void GetState(Vector3D &PosCopy, Vector3D &LookCopy, Vector3D &UpCopy,
                 Vector3D &SideCopy);
   
   // store the current camera state to the internal storage vectors
   void PushState();

   // sets camera position and orientation to given vectors
   // assumes NewLook, NewUp and NewSide are normalized for proper function
   void SetState(Vector3D const NewPos, Vector3D const NewLook, Vector3D const NewUp,
                 Vector3D const NewSide);

   // restore the state from the storage vectors to the camera
   void PopState();

   // translates camera forwards or backwards (i.e. along Look vector) by given
   //   distance
   void Zoom(double const Dist);

   // translates camera horizontally and vertically (i.e. along Side and Up
   //   vectors) by given distances
   void Pan(double const dX, double const dY);

   // rolls the camera (rotates around Look vector) by the given angle
   void Roll(double const Angle);

   // rotates camera around the given pivot point to simulate spinning all
   //   objects in the view
   // displacements are typically pixel offsets, i.e. the displacement of the
   //   mouse pointer in its current position from the initial drag point
   // PixelsPer180 is the distance to move to achieve a 180 degree rotation,
   //   about half of the largest viewport dimension works well
   void Orbit(Vector3D const &Pivot, int const dX, int const dY,
              double const PixelsPer180 = 400.0);

   // rolls the camera by the given angle around an axis through the camera
   //   position and the given pivot point to simulate rolling around all
   //   objects in the view
   void RollOrbit(Vector3D &Pivot, double const Angle);

   // return camera object to it's home position.  looks down it' Look vector
   // towards the head of the origin vector (center of the bounding box).
   void GoHome(Vector3D origin);

private:
   
   Vector3D PushedPos, PushedLook, PushedUp, PushedSide;

};

#endif // _CAMERA_H_
